package com.tao.mytestdd.datagrama

import java.net.DatagramPacket
import java.net.DatagramSocket

/**
 *reate by tao on{DATE}
 */
class DatagramService {
    lateinit var datagramService: DatagramSocket
    lateinit var datagramOperate: UDPDatagramOperate
    lateinit var udpSendManager: UDPSendManager
    var call: DatagramCall? = null

    fun init() {
        init(8080)
    }

    fun init(port: Int) {
        try {
            datagramOperate = UDPDatagramOperate()
            datagramService = DatagramSocket(port)
            udpSendManager = UDPSendManager(datagramService)
            datagramService.reuseAddress = true
            udpSendManager.local_service_port = datagramService.localPort
            
            if (!datagramService.isClosed) {
                call?.onOpen()
            }
            listener()
        } catch (e: Exception) {
            call?.onError("opend error", e)
            call?.onClose()
        }

    }

    fun close() {
        datagramService.close()
    }


    private fun recv(socket: DatagramSocket, receiveBuf: ByteArray): DatagramPacket? {
        val receiverPacket = DatagramPacket(receiveBuf, receiveBuf.size)
        if (socket.isClosed) {
            return receiverPacket
        }
        socket.receive(receiverPacket)
        return receiverPacket
    }

    /**
     * 监听数据
     */
    private fun listener() {
        Thread {
            try {
                while (!datagramService.isClosed) {
                    try {
                        val recv = recv(datagramService, ByteArray(65535))
                        recv?.let {
                            val msg = datagramOperate.receiverMsg(it)
                            msg?.let {
                                call?.onReceiver(msg)
                            }
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                        throw e
                    }
                    Thread.sleep(20)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                call?.onClose()
            }
        }.start()

    }

    /**
     * 发送数据
     */
    fun sendData(data: ByteArray, host: String, port: Int) {
        if (datagramService.isClosed) {
            call?.onError("datagramService unOpend", Exception("unOpend"))
            return
        }
        try {
            udpSendManager.sendData(data, host, port)
            call?.onSend(String(data))
        } catch (e: Exception) {
            call?.onError("send error", e)
        }
    }

    fun sendMsg(msg: String, host: String, port: Int) {
        sendData(msg.toByteArray(), host, port)
    }

    interface DatagramCall {
        fun onOpen()
        fun onClose()
        fun onError(msg: String, exception: Exception?)
        fun onReceiver(msg: DataEntity<String?>?)
        fun onSend(msg: String)
    }

}